// Here's the AnimatedTexture class code:

using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Storage;

namespace BumbleGame
{
    public class AnimatedTexture
    {
        public int framesWide, framesTall, FrameRight, FrameDown, HitBoxOffset, firstFrame, lastFrame, currentFrame;
        public Texture2D aTexture;
        private float TimePerFrame, TotalElapsed;
        private int FrameHeight, FrameWidth;
        private bool Paused, symmetricTexture, increasingFrames;
        private Vector2 SpriteOrigin;
        public Vector2 SpritePosition;
        //public BoundingBox HitBox;
        public HitBox2D HitBox2;
        public float SpriteRotation, SpriteScale, SpriteLayer;
        public float recHeight, recWidth; //experiment for rectangle drawing height stuff
        public Color tint;
        public SpriteEffects spriteFX;

        public AnimatedTexture()
        {
            HitBoxOffset = 0;
            SpriteRotation = 0f;
            SpriteScale = 1f;
            SpriteLayer = 1f;
            tint = Color.White;
            symmetricTexture = false;
            increasingFrames = true;
            spriteFX = SpriteEffects.None;
        }


        // AnimatedTexture.Load
        public void Load(GraphicsDevice device, ContentManager content, string asset, 
                         int FramesWide, int FramesTall, int FramesPerSec, int FirstFrame, int LastFrame, bool symmetric)
        {
            framesWide = FramesWide;
            framesTall = FramesTall;
            firstFrame = FirstFrame;
            //set current frame = the first frame in the sequence
            currentFrame = firstFrame;
            symmetricTexture = symmetric;
            lastFrame = LastFrame;
            aTexture = content.Load<Texture2D>(asset);
            TimePerFrame = (float)1 / FramesPerSec;
            FrameRight = 0;
            FrameDown = 0;
            TotalElapsed = 0;
            Paused = false;
            SpriteOrigin = new Vector2((aTexture.Width / framesWide) / 2, (aTexture.Height / framesTall) / 2);
            FrameWidth = aTexture.Width / framesWide;
            FrameHeight = aTexture.Height / framesTall;
            recHeight = FrameHeight;
            recWidth = FrameWidth;
        }

        // AnimatedTexture.UpdateFrame
        public void UpdateFrame(float elapsed)
        {
            // update hitbox coordinates
            /*HitBox = new BoundingBox(new Vector3((SpritePosition.X - 
SpriteOrigin.X + HitBoxOffset), (SpritePosition.Y - SpriteOrigin.Y + 
HitBoxOffset), 0),
                new Vector3((SpritePosition.X - SpriteOrigin.X - 
HitBoxOffset) + (aTexture.Width / framesWide),
                ((SpritePosition.Y - SpriteOrigin.Y - HitBoxOffset) + 
(aTexture.Height / framesTall)), 0));*/

            HitBox2 = new HitBox2D(new Vector2((SpritePosition.X - SpriteOrigin.X + HitBoxOffset), 
                                               (SpritePosition.Y - SpriteOrigin.Y + HitBoxOffset)),
                                   new Vector2((SpritePosition.X - SpriteOrigin.X - HitBoxOffset) + (aTexture.Width / framesWide), 
                                              ((SpritePosition.Y - SpriteOrigin.Y - HitBoxOffset) + (aTexture.Height / framesTall))));



            if (Paused)
                return;
            TotalElapsed += elapsed;
            if (TotalElapsed > TimePerFrame)
            {

                if (increasingFrames) currentFrame++;
                else currentFrame--;

                //reset to first frame if current frame has gone too far
                if ( !symmetricTexture && (currentFrame > lastFrame)) currentFrame = firstFrame;
                if (symmetricTexture && (currentFrame > lastFrame))
                {
                    currentFrame = lastFrame - 1;
                    increasingFrames = false;
                }

                if (symmetricTexture && (currentFrame < firstFrame))
                {
                    currentFrame = firstFrame + 1;
                    increasingFrames = true;
                }

                FrameDown = currentFrame / framesWide;
                if (currentFrame > framesWide - 1)
                {
                    FrameRight = currentFrame % framesWide;
                }
                else FrameRight = currentFrame;

                TotalElapsed -= TimePerFrame;
            }
        }

        // AnimatedTexture.DrawFrame
        public void DrawFrame(SpriteBatch Batch)
        {
            DrawFrame(Batch, FrameRight, FrameDown);
        }
        public void DrawFrame(SpriteBatch Batch, float fRecWidth, float fRecHeight)
        {
            int rectStartY = FrameHeight * FrameDown;
            int rectStartX = FrameWidth * FrameRight;
            this.recWidth = fRecWidth;
            this.recHeight = fRecHeight;

            Rectangle sourcerect = new Rectangle(rectStartX, rectStartY,
                                                 (int)recWidth, (int)recHeight);
            Batch.Draw(aTexture, SpritePosition, sourcerect, new Color(tint.R, tint.G, tint.B, (byte)BumbleGame.Game1.gSaturate), SpriteRotation, SpriteOrigin, SpriteScale, spriteFX, SpriteLayer);
        }
        internal void DrawFrame(SpriteBatch Batch, int FrameRight, int FrameDown)
        {
            int rectStartY = FrameHeight * FrameDown;
            if (recHeight != FrameHeight) rectStartY = (int)((FrameHeight * FrameDown) + FrameHeight - recHeight);

            int rectStartX = FrameWidth * FrameRight;
            if (recWidth != FrameWidth) rectStartX = (int)((FrameWidth * FrameRight) + FrameWidth - recWidth);
            
            Rectangle sourcerect = new Rectangle(rectStartX, rectStartY,
                                                 (int)recWidth, (int)recHeight);

            Batch.Draw(aTexture, SpritePosition, sourcerect, new Color(tint.R, tint.G, tint.B, (byte)BumbleGame.Game1.gSaturate), SpriteRotation, SpriteOrigin, SpriteScale, spriteFX, SpriteLayer);
        }

        public bool IsPaused
        {
            get { return Paused; }
        }
        public void Reset()
        {
            FrameRight = 0;
            FrameDown = 0;
            TotalElapsed = 0f;
        }
        public void Stop()
        {
            Pause();
            Reset();
        }
        public void Play()
        {
            Paused = false;
        }
        public void Pause()
        {
            Paused = true;
        }

        public void SetHitBoxOffset(int offset)
        {
            // prevents hit box from being inverted, which would be bad
            if ((offset < SpriteOrigin.X) && (offset < SpriteOrigin.Y))
            {
                HitBoxOffset = offset;
            }
            else HitBoxOffset = 0;
        }
    }

    // 2 dimensional hit detection box
    public class HitBox2D//:IEquatable<HitBox2D>
    {
        //upper left corner of the hitbox
        private Vector2 Min;
        //lower right corner of the hitbox
        private Vector2 Max;

        //constructor
        public HitBox2D(Vector2 min, Vector2 max)
        {
            Min = min;
            Max = max;
        }

        //checks if another hitbox has hit this one, returns true if hit is detected
        //works better if the larger hitbox = this.hitbox and the smaller hitbox = otherHitBox
        public bool Intersects(HitBox2D otherHitBox)
        {
            //upper left is otherHitBox.Min, lower right is otherHitBox.Max
            Vector2 otherUpperRight = new Vector2(otherHitBox.Max.X, otherHitBox.Min.Y);
            Vector2 otherLowerLeft = new Vector2(otherHitBox.Min.X, otherHitBox.Max.Y);
            Vector2 thisUpperRight = new Vector2(this.Max.X, this.Min.Y);
            Vector2 thisLowerLeft = new Vector2(this.Min.X, this.Max.Y);

            //check if any of the corner points of otherHitBox are contained by this hitbox.  otherhitbox corners are vector2's...
            // use contains function to see if they are in this hitbox
            if ( this.Contains(otherHitBox.Min) || this.Contains(otherUpperRight) || this.Contains(otherLowerLeft) || this.Contains(otherHitBox.Max) 
                || otherHitBox.Contains(this.Min) || otherHitBox.Contains(thisUpperRight) || otherHitBox.Contains(thisLowerLeft) || otherHitBox.Contains(this.Max)) 
                return true;

            else return false;
        }

        //returns true if the point is inside this hitbox
        public bool Contains(Vector2 point)
        {
            //looks like it's working right now
            if (point.X > this.Min.X && point.Y > this.Min.Y && point.X < this.Max.X && point.Y < this.Max.Y ) 
                return true;

            else return false;
        }

        //returns true if the other hitbox is inside this hitbox
        public bool Contains(HitBox2D otherHitBox)
        {
            if (this.Min.X < otherHitBox.Min.X && this.Min.Y < otherHitBox.Min.Y && this.Max.X > otherHitBox.Max.X && this.Max.Y > otherHitBox.Max.Y) 
                return true;

            else return false;
        }


    }
}



